﻿using System.Windows.Media;
using DimensionsHelper.Client.Helpers;
using DimensionsHelper.Common.Contracts;
using DimensionsHelper.Common.Contracts.Excel;
using DimensionsHelper.Common.Contracts.Excel.Options;
using DimensionsHelper.Common.TableFormatter;
using ExcelHAlign = DimensionsHelper.Common.Contracts.Excel.ExcelHAlign;
using ExcelVAlign = DimensionsHelper.Common.Contracts.Excel.ExcelVAlign;

namespace DimensionsHelper.Client.ViewModels.CsvFormatter;

public partial class RangeStyleOptionsViewModel
    : ObservableObject, IRangeStyleOptions, IProjectOption<RangeStyleOptions>
{
    private readonly CsvFormatterViewModel _project;


    [ObservableProperty]
    private bool _addAroundBorder;


    [ObservableProperty]
    private bool _addHorizontalBorder;


    [ObservableProperty]
    private bool _addVerticalBorder;


    [ObservableProperty]
    private bool _bold;


    [ObservableProperty]
    private BorderStyle _borderStyle = BorderStyle.None;


    [ObservableProperty]
    private Brush _fontColorBrush = Brushes.Black;


    [ObservableProperty]
    private FontFamilyInfo _fontFamily = FontFamilyHelper.DefaultFontFamily;


    [ObservableProperty]
    private double _fontSize = TableFormatterDefaultValues.FontSize;


    [ObservableProperty]
    private ExcelHAlign _hAlign;


    [ObservableProperty]
    private bool _hAlignCenter;


    [ObservableProperty]
    private bool _hAlignLeft = true;


    [ObservableProperty]
    private bool _hAlignRight;


    [ObservableProperty]
    private Brush _interiorBrush = Brushes.Transparent;


    [ObservableProperty]
    private bool _italic;


    [ObservableProperty]
    private string _numberFormatLocal = string.Empty;


    [ObservableProperty]
    private bool _underlined;


    [ObservableProperty]
    private UnderLineType _underLineType = UnderLineType.Single;

    private bool _updateInternal;


    [ObservableProperty]
    private ExcelVAlign _vAlign;


    [ObservableProperty]
    private bool _vAlignBottom;


    [ObservableProperty]
    private bool _vAlignCenter;


    [ObservableProperty]
    private bool _vAlignTop = true;


    [ObservableProperty]
    private bool _wrapText;

    public RangeStyleOptionsViewModel(IServiceProvider serviceProvider)
    {
        _project = serviceProvider.GetRequiredService<CsvFormatterViewModel>();
        PropertyChanged += OnAlignPropertyChanged;
    }


    public void LoadOption(RangeStyleOptions source)
    {
        FontSize = source.Font.FontSize;
        FontColorBrush = new SolidColorBrush(source.Font.FontColor.ToColor());
        UnderLineType = source.Font.UnderLine;
        WrapText = source.WrapText;
        HAlign = source.HAlign;
        VAlign = source.VAlign;
        Bold = source.Font.FontType.HasFlag(FontType.Bold);
        Underlined = source.Font.FontType.HasFlag(FontType.Underline);
        Italic = source.Font.FontType.HasFlag(FontType.Italic);

        if (!FontFamilyHelper.TryGetFontFamilyInfo(source.Font.FontFamily, out FontFamilyInfo? family))
        {
            family = FontFamilyHelper.DefaultFontFamily;
            _project.ReportService?.Warn("'{0}'不是有效的字体名，修改为默认值'{1}'", source.Font.FontFamily, family.Name);
        }

        FontFamily = family;
        InteriorBrush = new SolidColorBrush(source.InteriorColor.ToColor());
        NumberFormatLocal = source.NumberFormatLocal;
        BorderStyle = source.BorderStyle;
        AddHorizontalBorder = source.BorderPosition.HasFlag(BorderPosition.Horizontal);
        AddVerticalBorder = source.BorderPosition.HasFlag(BorderPosition.Vertical);
        AddAroundBorder = source.BorderPosition.HasFlag(BorderPosition.Around);
    }

    public bool TryWriteOption(RangeStyleOptions target)
    {
        target.InteriorColor = ((SolidColorBrush)InteriorBrush).Color.ToExcelStyleColor();
        target.NumberFormatLocal = NumberFormatLocal;
        target.BorderStyle = BorderStyle;

        if (AddAroundBorder)
        {
            target.BorderPosition |= BorderPosition.Around;
        }

        if (AddHorizontalBorder)
        {
            target.BorderPosition |= BorderPosition.Horizontal;
        }

        if (AddVerticalBorder)
        {
            target.BorderPosition |= BorderPosition.Vertical;
        }

        target.Font.FontFamily = FontFamily.Name;
        target.Font.FontSize = (float)FontSize;
        target.Font.FontColor = ((SolidColorBrush)FontColorBrush).Color.ToExcelStyleColor();
        target.Font.UnderLine = UnderLineType;
        target.WrapText = WrapText;
        target.HAlign = HAlign;
        target.VAlign = VAlign;

        if (Bold)
        {
            target.Font.FontType |= FontType.Bold;
        }

        if (Underlined)
        {
            target.Font.FontType |= FontType.Underline;
        }

        if (Italic)
        {
            target.Font.FontType |= FontType.Italic;
        }

        return true;
    }

    private void OnAlignPropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (_updateInternal)
        {
            return;
        }

        switch (e)
        {
            case { PropertyName: nameof(HAlign) }:
            {
                _updateInternal = true;

                switch (HAlign)
                {
                    case ExcelHAlign.Center:
                    {
                        HAlignCenter = true;
                        HAlignLeft = false;
                        HAlignRight = false;
                        break;
                    }

                    case ExcelHAlign.Left:
                    {
                        HAlignCenter = false;
                        HAlignLeft = true;
                        HAlignRight = false;
                        break;
                    }

                    case ExcelHAlign.Right:
                    {
                        HAlignCenter = false;
                        HAlignLeft = false;
                        HAlignRight = true;
                        break;
                    }
                }

                _updateInternal = false;
                break;
            }

            case { PropertyName: nameof(HAlignLeft) }:
            {
                _updateInternal = true;

                if (HAlignCenter)
                {
                    HAlignCenter = false;
                    HAlignRight = false;
                }
                else
                {
                    HAlignLeft = true;
                }

                HAlign = ExcelHAlign.Left;
                _updateInternal = false;
                break;
            }

            case { PropertyName: nameof(HAlignCenter) }:
            {
                _updateInternal = true;

                if (HAlignCenter)
                {
                    HAlignLeft = false;
                    HAlignRight = false;
                    HAlign = ExcelHAlign.Center;
                }
                else
                {
                    HAlignLeft = true;
                    HAlign = ExcelHAlign.Left;
                }

                _updateInternal = false;
                break;
            }

            case { PropertyName: nameof(HAlignRight) }:
            {
                _updateInternal = true;

                if (HAlignRight)
                {
                    HAlignLeft = false;
                    HAlignCenter = false;
                    HAlign = ExcelHAlign.Right;
                }
                else
                {
                    HAlignLeft = true;
                    HAlign = ExcelHAlign.Left;
                }

                _updateInternal = false;
                break;
            }

            case { PropertyName: nameof(VAlign) }:
            {
                _updateInternal = true;

                switch (VAlign)
                {
                    case ExcelVAlign.Top:
                    {
                        VAlignTop = true;
                        VAlignCenter = false;
                        VAlignBottom = false;
                        break;
                    }

                    case ExcelVAlign.Center:
                    {
                        VAlignTop = false;
                        VAlignCenter = true;
                        VAlignBottom = false;
                        break;
                    }

                    case ExcelVAlign.Bottom:
                    {
                        VAlignTop = false;
                        VAlignCenter = false;
                        VAlignBottom = true;
                        break;
                    }
                }

                _updateInternal = false;
                break;
            }

            case { PropertyName: nameof(VAlignTop) }:
            {
                _updateInternal = true;

                if (VAlignTop)
                {
                    VAlignCenter = false;
                    VAlignBottom = false;
                }
                else
                {
                    VAlignTop = true;
                }

                VAlign = ExcelVAlign.Top;
                _updateInternal = false;
                break;
            }

            case { PropertyName: nameof(VAlignCenter) }:
            {
                _updateInternal = true;

                if (VAlignCenter)
                {
                    VAlignTop = false;
                    VAlignBottom = false;
                    VAlign = ExcelVAlign.Center;
                }
                else
                {
                    VAlignTop = true;
                    VAlign = ExcelVAlign.Top;
                }

                _updateInternal = false;
                break;
            }

            case { PropertyName: nameof(VAlignBottom) }:
            {
                _updateInternal = true;

                if (VAlignBottom)
                {
                    VAlignTop = false;
                    VAlignCenter = false;
                    VAlign = ExcelVAlign.Bottom;
                }
                else
                {
                    VAlignTop = true;
                    VAlign = ExcelVAlign.Top;
                }

                _updateInternal = false;
                break;
            }
        }
    }
}